<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>REINDEX</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="REFENTRY">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="sql-reassign-owned.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="sql-reassign-owned.html">快退</a></td><td width="60%" align="center" valign="bottom"></td><td width="10%" align="right" valign="top"><a href="sql-release-savepoint.html">快进</a></td><td width="10%" align="right" valign="top"><a href="sql-release-savepoint.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<h1><a name="SQL-REINDEX"></a>REINDEX</h1>
<div class="REFNAMEDIV"><a name="AEN52988"></a><h2>名称</h2>REINDEX&nbsp;--&nbsp;重建索引</div>
<a name="AEN52991"></a>
<div class="REFSYNOPSISDIV"><a name="AEN52993"></a><h2>语法</h2>
<pre class="SYNOPSIS">REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <tt class="REPLACEABLE"><i>name</i></tt> [ FORCE ]</pre>
</div>
<div class="REFSECT1"><a name="AEN52996"></a><h2>描述</h2>
<p><tt class="COMMAND">REINDEX</tt> 使用表中的数据重建索引。使用 <tt class="COMMAND">REINDEX</tt> 有两个主要原因：</p>
<ul>
<li><p>索引崩溃，并且不再包含有效的数据。尽管理论上这是不可能发生的，但实际上索引会因为软件毛病或者硬件问题而崩溃。<tt class="COMMAND">REINDEX</tt> 提供了一个恢复方法。</p></li>
<li><p>索引变得"臃肿"，包含大量的空页或接近空页。这个问题在某些罕见访问模式时会发生在 B-tree 索引上。<tt class="COMMAND">REINDEX</tt> 通过写一个不带无用索引页的新索引提供了缩小索引空间消耗的途径。参阅<a href="routine-reindex.html">节22.2</a>获取更多信息。</p></li>
<li><p>为索引更改了存储参数(例如填充因子)，并且希望这个更改完全生效。</p></li>
<li><p>使用 <tt class="LITERAL">CONCURRENTLY</tt> 选项创建索引失败，留下了一个"非法"索引。这样的索引毫无用处，但是可以通过 <tt class="COMMAND">REINDEX</tt> 重建新索引来覆盖。注意，<tt class="COMMAND">REINDEX</tt> 不能并发创建。要在生产环境中重建索引并且尽可能减小对尖峰负载的影响，可以先删除旧索引，然后使用 <tt class="COMMAND">CREATE INDEX CONCURRENTLY</tt> 命令重建新索引。</p></li>
</ul>
</div>
<div class="REFSECT1"><a name="AEN53020"></a><h2>参数</h2>
<div class="VARIABLELIST">
<dl>
<dt><tt class="LITERAL">INDEX</tt></dt>
<dd><p>重新建立指定的索引</p></dd>
<dt><tt class="LITERAL">TABLE</tt></dt>
<dd><p>重新建立指定表的所有索引。如果表有从属的"TOAST"表，那么这个表也会重新索引。</p></dd>
<dt><tt class="LITERAL">DATABASE</tt></dt>
<dd><p>重建当前数据库里的所有索引。除非在独立模式下(见下文)，否则会忽略在共享系统表上的索引。这种形式的 <tt class="COMMAND">REINDEX</tt> 不能在事务块中执行。</p></dd>
<dt><tt class="LITERAL">SYSTEM</tt></dt>
<dd><p>在当前数据库上重建所有系统表上的索引。不会处理在用户表上的索引。另外，除非是在独立模式下(见下文)，否则会忽略在共享系统表上的索引。这种形式的 <tt class="COMMAND">REINDEX</tt> 不能在事务块中执行。</p></dd>
<dt><tt class="REPLACEABLE"><i>name</i></tt></dt>
<dd><p>需要重建索引的索引、表、数据库的名称。表和索引名可以有模式修饰。目前，<tt class="COMMAND">REINDEX DATABASE</tt> 和 <tt class="COMMAND">REINDEX SYSTEM</tt> 只能重建当前数据库的索引，因此其参数必须匹配当前数据库的名字。</p></dd>
<dt><tt class="LITERAL">FORCE</tt></dt>
<dd><p>这是一个废弃的选项，如果声明，会被忽略。</p></dd>
</dl>
</div>
</div>
<div class="REFSECT1"><a name="AEN53058"></a><h2>注意</h2>
<p>如果你怀疑一个用户表上的索引崩溃了，你可以简单地使用 <tt class="COMMAND">REINDEX INDEX</tt> 重建该索引，或者使用 <tt class="COMMAND">REINDEX TABLE</tt> 重建该表上的所有索引。</p>
<p>如果你从一个崩溃的系统表索引上恢复，事情会更棘手一些。这种情况下，系统必须不能使用任何有疑问的索引。实际上，在这种情况下，你可能发现服务器进程在启动之后马上就崩溃了，因为依赖于崩溃了的索引。要想安全恢复，服务器必须带着 <tt class="OPTION">-P</tt> 选项启动，它禁止服务器在查找系统表的时候使用索引。</p>
<p>达到这个目的的一个方法是停止服务器然后带着 <tt class="OPTION">-P</tt> 命令行选项启动一个独立的 PostgreSQL 服务器。然后，根据你希望恢复的程度，发出 <tt class="COMMAND">REINDEX DATABASE</tt>, <tt class="COMMAND">REINDEX SYSTEM</tt>, <tt class="COMMAND">REINDEX TABLE</tt>, <tt class="COMMAND">REINDEX INDEX</tt> 命令。如果还有怀疑，使用 <tt class="COMMAND">REINDEX SYSTEM</tt> 选择重新构造数据库中全部的系统索引。然后退出独立服务器会话并且重启普通的服务器。参阅 <a href="app-postgres.html"><span class="APPLICATION">postgres</span></a> 手册页获取有关如何与独立服务器交互的信息。</p>
<p>另外，一个普通的会话可以在其命令行选项里使用 <tt class="OPTION">-P</tt> 选项启动。这么做的方法因不同的客户端而异，但是在所有基于 <span class="APPLICATION">libpq</span> 的客户端上，都可以通过在启动客户端之前设置 <tt class="ENVAR">PGOPTIONS</tt> 环境变量为 <tt class="LITERAL">-P</tt> 来实现。请注意尽管这个方法并不要求锁住其它客户端，但是禁止其它客户端连接受损的数据库，直到完成修补是一个明智的选择。</p>
<p>如果怀疑任何共享的系统表(它们是 <tt class="STRUCTNAME">pg_authid</tt>, <tt class="STRUCTNAME">pg_auth_members</tt>, <tt class="STRUCTNAME">pg_database</tt>, <tt class="STRUCTNAME">pg_pltemplate</tt>, <tt class="STRUCTNAME">pg_shdepend</tt>, <tt class="STRUCTNAME">pg_shdescription</tt>, <tt class="STRUCTNAME">pg_tablespace</tt>)的索引损坏，那么必须用独立服务器的方式来修复它。<tt class="COMMAND">REINDEX</tt> 不能在多用户环境下处理共享系统表。</p>
<p>除了共享系统表之外的所有索引，<tt class="COMMAND">REINDEX</tt> 是抗崩溃并且是事务安全的。<tt class="COMMAND">REINDEX</tt> 对于共享的索引而言不是抗崩溃的，这就是为什么不允许在正常操作中这么使用的原因。如果在重新对一个共享表进行索引的时候发生了崩溃，那么在纠正问题之前，就不可能重新启动普通的服务器。一个建立了一部分的共享索引的典型症状是"index is not a btree"错误。</p>
<p><tt class="COMMAND">REINDEX</tt> 类似于删除并重建索引，表现在它们都是从零开始重建。不过，从锁的角度考虑，两者是有区别的。<tt class="COMMAND">REINDEX</tt> 锁住对表的写操作，但是不锁读操作。并且它还在被处理的特定索引上保持一个排他锁，这样它将阻止试图使用该索引的读操作。相比之下，<tt class="COMMAND">DROP INDEX</tt> 在父表上短暂的保持一个排他锁，同时锁住读和写。随后的 <tt class="COMMAND">CREATE INDEX</tt> 锁住写操作但是不会锁住读操作；因为索引还不存在，所以不会有试图使用它的读操作，意味着操作中不会有阻塞，只不过读操作会被迫只能使用顺序扫描。另外一个重要的环节是删除/重建的方法让所有使用索引的缓冲的查询规划都失效，而 <tt class="COMMAND">REINDEX</tt> 不会。</p>
<p>对一个索引或者表进行重建索引，要求你是该索引或者表的所有者。对一个数据库重建索引要求你是该数据库的所有者(注意，可以重建其它用户拥有的索引)。当然，超级用户总是可以重建所有索引。</p>
<p>PostgreSQL 8.1 之前，<tt class="COMMAND">REINDEX DATABASE</tt> 只处理系统索引，而不是人们从名字猜测的那样，处理所有索引。这个行为现在已经改变了，以减少意外的因素。旧的行为可以通过 <tt class="COMMAND">REINDEX SYSTEM</tt> 获得。</p>
<p>PostgreSQL 7.4 之前，<tt class="COMMAND">REINDEX TABLE</tt> 并不自动处理 TOAST 表，因此这些表必须用独立的命令进行处理。这么做仍然可以，但是已经多余了。</p>
</div>
<div class="REFSECT1"><a name="AEN53106"></a><h2>例子</h2>
<p>重建一个单独的索引：</p>
<pre class="PROGRAMLISTING">REINDEX INDEX my_index;</pre>
<p>重建表 <tt class="LITERAL">my_table</tt> 上的所有索引：</p>
<pre class="PROGRAMLISTING">REINDEX TABLE my_table;</pre>
<p>重建一个数据库上的所有系统索引，不管系统索引是否仍然有效：</p>
<pre class="PROGRAMLISTING">$ <kbd class="USERINPUT">export PGOPTIONS="-P"</kbd>
$ <kbd class="USERINPUT">psql broken_db</kbd>
...
broken_db=&gt; REINDEX DATABASE broken_db;
broken_db=&gt; \q</pre>
</div>
<div class="REFSECT1"><a name="AEN53117"></a><h2>兼容性</h2>
<p>SQL 标准里没有 <tt class="COMMAND">REINDEX</tt> 命令。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="sql-reassign-owned.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="sql-release-savepoint.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">REASSIGN OWNED</td><td width="34%" align="center" valign="top"><a href="sql-commands.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">RELEASE SAVEPOINT</td></tr>
</table>
</div>
</body></html>